package com.wheesper.www.WheesperServer.Services;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;

import com.Wheesper.www.WheesperServer.Model.User;
import com.Wheesper.www.WheesperServer.Model.UserCenter;
import com.wheesper.www.WheesperServer.Common.OfflineMessageTrusteeship;
import com.wheesper.www.WheesperServer.Net.Session.IOSession;
import com.wheesper.www.WheesperServer.Utils.Logger;
import ProtocolBuffer.ProtoMessageOuterClass.*;

public class LogController {
	
	private static LogController _instance = new LogController();
	public static LogController Instance() {
		return _instance;
	}
	private  LogController() {
		_users_online = new HashSet<User>();
		_session2user = new HashMap<IOSession,User>();
		_user2session = new HashMap<User,IOSession>();
	}
	
	private Set<User> _users_online;
	private Map<IOSession,User> _session2user;
	private Map<User,IOSession> _user2session;
	
	private boolean check(String email,String password) {
		String psw = UserCenter.Instance().Password(email);
		return (psw != null) &&(psw.contentEquals(password));
	}
	private boolean check(Integer id,String password) {
		String psw = UserCenter.Instance().Password(id);
		return (psw != null) &&(psw.contentEquals(password));
	}
	
	//helper Method
	private void logonSuccessfullyResponse(IOSession session,String email) {
		SigninResponse response = SigninResponse.newBuilder()
				.setMailAddress(email)
				.setStatus(true)
				.build();
		ProtoMessage message = ProtoMessage.newBuilder()
				.setSigninResponse(response)
				.build();
		session.writeToRemote(message.toByteArray());
	}
	private void logonFailedResponse(IOSession session,String email) {
		SigninResponse response = SigninResponse.newBuilder()
				.setMailAddress(email)
				.setStatus(false)
				.build();
		ProtoMessage message = ProtoMessage.newBuilder()
				.setSigninResponse(response)
				.build();
		session.writeToRemote(message.toByteArray());
	}
	
	private void logoutSuccessfullyResponse(IOSession session) {
		//TODO:
	}
	
	public static void offlineMessagesPushing(IOSession session,ArrayList<ProtoMessage> messages) {
		messages.forEach(new Consumer<ProtoMessage>() {
			@Override
			public void accept(ProtoMessage t) {
				session.writeToRemote(t.toByteArray());
			}
		});
	}
	
	
	public void logout(IOSession session) {
		User user = _session2user.get(session);
		session.disconneted();
		_users_online.remove(user);
		_session2user.remove(session);
		_user2session.remove(user);
		System.out.println("User Disconnected!");
	}
	
	public void logon(IOSession session,String email,String password){
		try {
			if(check(email,password)) {
				User email2user = UserCenter.Instance().UserObject(email);
				if(email2user == null) {
					throw new Exception("User of email:"
							+ email + " doesnt existed!");
				}
				_users_online.add(email2user);
				_session2user.put(session, email2user);
				_user2session.put(email2user, session);
				//登录成功
				logonSuccessfullyResponse(session,email);
				Logger.Instance().logging("[Log on Successfully]{\n"
						+email2user.toString() + "\n}");

			}else {
				logonFailedResponse(session,email);
				Logger.Instance().logging("[Log on Failed]{\n"
						+ "User:" + email + "\n}");
			}
		}catch(Exception e) {
			Logger.Instance().logging(e.getMessage());
			e.printStackTrace();
			logonFailedResponse(session,email);
			Logger.Instance().logging("[Log on Failed]{\n"
					+ "User:" + email 
					+ "Reason:Unknown Exception throw!"
					+ "\n}");
		}
	}
	
	public Map<User,IOSession> User2Session(){
		return this._user2session;
	}
	
	public User GetOnlineUserBy(IOSession session) {
		return _session2user.get(session);
	}
	
	public IOSession GetIOSessionBy(User user) {
		return _user2session.get(user);
	}
}
